// Copyright©,2020-2025
// Author: caocheng
// Version: 1.0.0
// Date: 2021/3/2 11:19
// Description：
package SummerCore

import (
	"container/list"
	"context"
	"sync"

	"gitee.com/chrischo/go-summer/summer/summer-logger"
	"gitee.com/chrischo/go-summer/summer/summer-utils"
)

// defaultApplicationContext SpringContext 的默认实现
type defaultApplicationContext struct {
	// 属性值列表接口
	Properties

	// 上下文接口
	wg     sync.WaitGroup
	ctx    context.Context
	cancel context.CancelFunc

	profile   string     // 运行环境
	configers *list.List // 配置方法集合
}

// NewDefaultApplicationContext defaultApplicationContext 的构造函数
func NewDefaultApplicationContext() *defaultApplicationContext {
	ctx, cancel := context.WithCancel(context.Background())
	return &defaultApplicationContext{
		ctx:        ctx,
		cancel:     cancel,
		Properties: NewDefaultProperties(),
		configers:  list.New(),
	}
}

// Context 返回上下文接口
func (ctx *defaultApplicationContext) Context() context.Context {
	return ctx.ctx
}

// GetProfile 返回运行环境
func (ctx *defaultApplicationContext) GetProfile() string {
	return ctx.profile
}

// SetProfile 设置运行环境
func (ctx *defaultApplicationContext) SetProfile(profile string) {
	ctx.profile = profile
}

// resolveConfigers 对 Config 函数进行决议是否能够保留它
func (ctx *defaultApplicationContext) resolveConfigers() {

	// 对 config 函数进行决议
	for e := ctx.configers.Front(); e != nil; {
		next := e.Next()
		configer := e.Value.(*Configer)
		if ok := configer.checkCondition(ctx); !ok {
			ctx.configers.Remove(e)
		}
		e = next
	}

	// 对 config 函数进行排序
	ctx.configers = SummerUtils.TripleSorting(ctx.configers, getBeforeConfigers)
}

// runConfigers 执行 Config 函数
func (ctx *defaultApplicationContext) runConfigers() {
	for e := ctx.configers.Front(); e != nil; e = e.Next() {
		configer := e.Value.(*Configer)
		if err := configer.run(ctx); err != nil {
			panic(err)
		}
	}
}

// Close 关闭容器上下文，用于通知 Bean 销毁等，该函数可以确保 Bean 的销毁顺序和注入顺序相反。
func (ctx *defaultApplicationContext) Close(beforeDestroy ...func()) {

	// 上下文结束
	ctx.cancel()

	// 调用 destroy 之前的钩子函数
	for _, f := range beforeDestroy {
		f()
	}

	// 等待 safe goroutines 全部退出
	ctx.wg.Wait()

	SummerLogger.Info("safe goroutines exited")
}

func (ctx *defaultApplicationContext) AutoConfig() {
	ctx.resolveConfigers()

	ctx.runConfigers()
}

// Run 根据条件判断是否立即执行一个一次性的任务
func (ctx *defaultApplicationContext) Run(fn interface{}, tags ...string) *Runner {
	return newRunner(ctx, fn, tags)
}

// RunNow 立即执行一个一次性的任务
func (ctx *defaultApplicationContext) RunNow(fn interface{}, tags ...string) error {
	return ctx.Run(fn, tags...).When(true)
}

// Config 注册一个配置函数
func (ctx *defaultApplicationContext) Config(fn interface{}, tags ...string) *Configer {
	return ctx.ConfigWithName("", fn, tags...)
}

// ConfigWithName 注册一个配置函数，名称的作用是对 Config 进行排重和排顺序。
func (ctx *defaultApplicationContext) ConfigWithName(name string, fn interface{}, tags ...string) *Configer {
	configer := newConfiger(name, fn, tags)
	ctx.configers.PushBack(configer)
	return configer
}

// SafeGoroutine 安全地启动一个 goroutine
func (ctx *defaultApplicationContext) SafeGoroutine(fn GoFunc) {
	ctx.wg.Add(1)
	go func() {
		defer ctx.wg.Done()

		defer func() {
			if err := recover(); err != nil {
				SummerLogger.Error(err)
			}
		}()

		fn()
	}()
}
